/**
 * 
 */
package de.fsujena.chat_pi.server.handler;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import de.fsujena.chat_pi.ressources.Room;
import de.fsujena.chat_pi.ressources.User;
import de.fsujena.chat_pi.ressources.User.ROLE;
import de.fsujena.chat_pi.ressources.message.SysMessage;
import de.fsujena.chat_pi.ressources.message.SysMessage.CATEGORY;
import de.fsujena.chat_pi.ressources.message.SysMessage.MESSAGE;
import de.fsujena.chat_pi.server.Server;
import de.fsujena.chat_pi.server.listener.MessageListener;
import de.fsujena.chat_pi.server.userInterface.GraphicalUI;

/**
 * @author Erik Hebestreit
 *
 */
public class SysMessageHandler {
	
	SysMessage message = null;
	Server serverObject;
	MessageListener msgListener;

	/**
	 * Constructor.
	 */
	public SysMessageHandler(MessageListener msgListener) {
		this.msgListener = msgListener;
		this.serverObject=msgListener.serverObject;
	}
	
	public boolean handleSysMessage(SysMessage message) {
		this.message = message;
		return filterCategory();		
	}

	/**
	 * process the received message and call the appropriate methods
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private boolean filterCategory() {
		switch (message.getCategory()) {					//filter message type
		case CONNECTION:
			switch (message.getMessage()){					//filter message
			case DISCONNECTED:
				//msgListener.distributeMsg(message);
				msgListener.close(false);
				break;
			default:
				break;
			}
			break;
		case LOGIN:
			switch (message.getMessage()){
			case WANT_TO_LOGIN:								
				if (msgListener.loggedIn) {
					msgListener.sendSysMessage(CATEGORY.LOGIN, MESSAGE.ALREADY_LOGGED_IN);
					}else{
						return userLogin();
				}
				break;
			case LOGGED_OUT:
					msgListener.logout();
					break;
			default:
				break;
			}
			break;
			
		case REGISTRATION:
			switch(message.getMessage()){
			case WANT_TO_REGISTER:
				return register();
			case REMOVE_ME:								//user wants to removes himself from the list
				int userNum = msgListener.serverObject.networkListener.userExists(message.getSenderUsername());			//get the index of the user in the list
				if (userNum >= 0) {																						//verify that the user exists
					msgListener.serverObject.networkListener.messageListener.get(userNum).sendSysMessage(CATEGORY.STATUS, MESSAGE.YOU_ARE_REMOVED);//tell him that he going to be removed
					msgListener.serverObject.networkListener.removeClient(message.getSenderUsername());					//close connection
				}
				
				msgListener.serverObject.userManager.removeUser(message.getSenderUsername());							//remove user from list
				break;
				
			default:
				break;
			}
			break;
			
		case CHANGE_USERNAME:
			if (message.getMessage() == MESSAGE.WANT_TO_CHANGE_USERNAME) {
				return changeUsername();
			}
			break;
			
		case CHANGE_PASSWORD:
			if (message.getMessage() == MESSAGE.WANT_TO_CHANGE_PASSWORD) {
				return changePassword();
			}
			break;
			
		case STATUS:
			switch (message.getMessage()) {
			case REQUEST_USER_LIST:
				msgListener.sendUserList();
				break;
			case REQUEST_ADMIN_LIST:
				msgListener.sendSysMessage(CATEGORY.STATUS, MESSAGE.SEND_ADMIN_LIST, null,msgListener.serverObject.userManager.adminlist() );
				break;
			case REQUEST_MOD_LIST:
				msgListener.sendSysMessage(CATEGORY.STATUS, MESSAGE.SEND_MOD_LIST, null,msgListener.serverObject.userManager.modlist() );
				break;
			case REQUEST_ROLE:
				msgListener.sendSysMessage(CATEGORY.STATUS,MESSAGE.SEND_ROLE,null,msgListener.serverObject.userManager.checkUserRole(msgListener.username));
				break;
			default:
				break;
			}
			break;
			
		case ADMIN:
			if (msgListener.serverObject.userManager.checkUserRole(msgListener.username) != User.ROLE.ADMIN) {
				msgListener.sendSysMessage(CATEGORY.STATUS, MESSAGE.NO_ADMIN);
				break;
			}
			
			switch (message.getMessage()) {
			case REMOVE_USER:
				int userNum = msgListener.serverObject.networkListener.userExists(message.getMessageString());
				if (userNum >= 0) {
					msgListener.serverObject.networkListener.messageListener.get(userNum).sendSysMessage(CATEGORY.STATUS, MESSAGE.YOU_ARE_REMOVED);
					msgListener.serverObject.networkListener.removeClient(message.getMessageString());
				}
				
				msgListener.serverObject.userManager.removeUser(message.getMessageString());
				break;

			default:
				break;
			}
			
			break;
			
		case MODERATE:
			if (msgListener.serverObject.userManager.checkUserRole(msgListener.username) != User.ROLE.MODERATOR && msgListener.serverObject.userManager.checkUserRole(msgListener.username) != User.ROLE.ADMIN) {
				msgListener.sendSysMessage(CATEGORY.STATUS, MESSAGE.NO_MOD);
				break;
			}
			
			int userNum;
			
			switch (message.getMessage()) {
			case BANN_USER:
				userNum = msgListener.serverObject.networkListener.userExists(message.getMessageString());
				if (userNum >= 0) {
					msgListener.distributeMsg(message);
					try {
						msgListener.connector.sendMessageObject(message);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					msgListener.serverObject.networkListener.removeClient(message.getMessageString());
				}
				
				msgListener.serverObject.userManager.bannUser(message.getMessageString());
				break;
				
			case KICK_USER:
				userNum = msgListener.serverObject.networkListener.userExists(message.getMessageString());
				if (userNum >= 0) {
					msgListener.distributeMsg(message);
					try {
						msgListener.connector.sendMessageObject(message);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					msgListener.serverObject.networkListener.removeClient(message.getMessageString());
				}
				break;
				
			case UNBANN_USER:
				msgListener.serverObject.userManager.unbannUser(message.getMessageString());
				break;
			case USER_WARNING:
				String tempUser=message.getMessageString();
				if((msgListener.serverObject.userManager.checkUserExists(tempUser))&&(msgListener.serverObject.networkListener.userExists(tempUser)!=-1)){
					try {
						msgListener.serverObject.networkListener.messageListener.get(serverObject.networkListener.userExists(tempUser)).connector.sendGeneralObject(message);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}else{
					msgListener.sendSysMessage(CATEGORY.STATUS, MESSAGE.USER_DONT_EXIST,tempUser);
				}
				break;
			default:
				break;
			}
			break;
		case ROOMMANAGEMENT:
			switch (message.getMessage()) {
			case REQUEST_ROOM_LIST:
				msgListener.sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.SEND_ROOM_LIST, "SERVER", msgListener.serverObject.roomManager.foyer.copyRoom());
				break;
			case REQUEST_ROOM_DIR:
				msgListener.sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.SEND_ROOM_DIR, "SERVER", msgListener.serverObject.userManager.users.get(msgListener.username).dir);
				break;
			case WANT_TO_ENTER_ROOM:
				if(message.getMessageObject() instanceof List<?>){
					List<String> tempdir=(List<String>)message.getMessageObject();
					switch (msgListener.serverObject.roomManager.moveUserTo(msgListener.serverObject.userManager.users.get(msgListener.username), tempdir)){
					case 0:
						//msgListener.sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.ENTER_ROOM, msgListener.serverObject.roomManager.getRoom(msgListener.serverObject.userManager.users.get(msgListener.username).dir).getName(),msgListener.serverObject.roomManager.getRoom(msgListener.serverObject.userManager.users.get(msgListener.username).dir));
						SysMessage msg=new SysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.ENTER_ROOM, msgListener.username,msgListener.serverObject.roomManager.getRoom(msgListener.serverObject.userManager.users.get(msgListener.username).dir));
						msg.setSent(new Date());
						msg.setSenderUsername("SERVER");
						msgListener.distributeMsg(msg);
						msgListener.serverObject.ui.postInfo(msgListener.username+" entered:"+msgListener.serverObject.roomManager.getRoom(tempdir).getName());
						SysMessage msg2=new SysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.SEND_ROOM_LIST, "SERVER", msgListener.serverObject.roomManager.foyer.copyRoom());
						msg2.setSent(new Date());
						msg2.setSenderUsername("SERVER");
						msgListener.serverObject.networkListener.distributeMsg(msg2);
						break;
					case 1:
						msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.ROOM_DONT_EXISTS);
						break;
					case 2:
						msgListener.serverObject.ui.postError("non existing user tryed to enter a room");
						break;
					case 3:
						msgListener.sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.NOT_ALLOWED_IN_THIS_ROOM);
						break;
					case 4:
						int i=serverObject.networkListener.userExists(serverObject.roomManager.getRoom(tempdir).getOwner().name);
						if(i==-1){
						msgListener.sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.ROOM_IS_PRIVATE,serverObject.roomManager.getRoom(tempdir).getOwner().name);
						}else{
							serverObject.networkListener.messageListener.get(i).sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.WANT_ON_WHITELIST, msgListener.username, tempdir);
							msgListener.sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.WANT_ON_WHITELIST_REQUESTED);
						}
						break;
						
					case 5:
						msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.NEED_MOD_RIGHTS);
						break;
					case 6:
						msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.NEED_ADMIN_RIGHTS);
						break;
					case 7:
						msgListener.serverObject.ui.postError("unknown error while creating a room");
						break;
					default:
						break;
					}
				}
				break;
			case CREATE_ROOM:
				if (msgListener.serverObject.userManager.users.get(msgListener.username).role==ROLE.ADMIN){
					if(message.getMessageObject() instanceof List<?>){
						List<String> tempdir=(List<String>)message.getMessageObject();
					if(msgListener.serverObject.roomManager.createRoom(tempdir,null)){
						SysMessage msg=new SysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.ROOM_WAS_CREATED, msgListener.username,msgListener.serverObject.roomManager.getRoom(msgListener.serverObject.userManager.users.get(msgListener.username).dir));
						msg.setSent(new Date());
						msg.setSenderUsername("SERVER");
						msgListener.distributeMsg(msg);
						msgListener.serverObject.ui.postInfo("Room "+msgListener.serverObject.roomManager.getRoom(tempdir).getName()+" was created by "+msgListener.username);
						SysMessage msg2=new SysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.SEND_ROOM_LIST, "SERVER", msgListener.serverObject.roomManager.foyer.copyRoom());
						msg2.setSent(new Date());
						msg2.setSenderUsername("SERVER");
						msgListener.serverObject.networkListener.distributeMsg(msg2);
						}else{
						//TODO error handling
							msgListener.sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.ERROR_CREATING_ROOM);
					}
					}else{
					//TODO error handling	
					}
				}else{
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.NEED_ADMIN_RIGHTS);
				}
				
				break;
				case CREATE_PRIVATE_ROOM:
						if(message.getMessageObject() instanceof List<?>){
							List<String> tempdir=(List<String>)message.getMessageObject();
						if(msgListener.serverObject.roomManager.createRoom(tempdir,msgListener.serverObject.userManager.getUser(msgListener.username))){
							SysMessage msg=new SysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.ROOM_WAS_CREATED, msgListener.username,msgListener.serverObject.roomManager.getRoom(msgListener.serverObject.userManager.users.get(msgListener.username).dir));
							msg.setSent(new Date());
							msg.setSenderUsername("SERVER");
							msgListener.distributeMsg(msg);
							msgListener.serverObject.ui.postInfo("Room "+msgListener.serverObject.roomManager.getRoom(tempdir).getName()+" was created by "+msgListener.username);
							SysMessage msg2=new SysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.SEND_ROOM_LIST, "SERVER", msgListener.serverObject.roomManager.foyer.copyRoom());
							msg2.setSent(new Date());
							msg2.setSenderUsername("SERVER");
							msgListener.serverObject.networkListener.distributeMsg(msg2);
							}else{
							//TODO error handling
						}
						}else{
						//TODO error handling	
						}
					
					
					break;
			case REMOVE_ROOM:
				if (msgListener.serverObject.userManager.users.get(msgListener.username).role==ROLE.ADMIN){
					if(message.getMessageObject() instanceof List<?>){
						List<String> tempdir=(List<String>)message.getMessageObject();
					switch (msgListener.serverObject.roomManager.removeRoom(tempdir)){
					case 0:
					SysMessage msg=new SysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.ROOM_REMOVED, msgListener.username,msgListener.serverObject.roomManager.getRoom(msgListener.serverObject.userManager.users.get(msgListener.username).dir));
					msg.setSent(new Date());
					msg.setSenderUsername("SERVER");
					msgListener.distributeMsg(msg);	
					String roomname="";
					for(int i=0;i<tempdir.size();i++){
						roomname=roomname+tempdir.get(i)+"/";
					}
					msgListener.serverObject.ui.postInfo("Room "+roomname+" was removed by "+msgListener.username);
					SysMessage msg2=new SysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.SEND_ROOM_LIST, "SERVER", msgListener.serverObject.roomManager.foyer.copyRoom());
					msg2.setSent(new Date());
					msg2.setSenderUsername("SERVER");
					msgListener.serverObject.networkListener.distributeMsg(msg2);
					break;
					default:
						break;
					}
					}else{
					//TODO error handling	
					}
				}else{
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.NEED_ADMIN_RIGHTS);
				}
				
				break;
			case AVAILABLE_ROOMS:
				if(message.getMessageObject() instanceof List<?>){
					List<String> tempdir=(List<String>)message.getMessageObject();
				Room tempRoom=msgListener.serverObject.roomManager.getRoom(tempdir);
				List<String> childreen=tempRoom.getChildren();
				childreen.clear();
//				List<String> childreen=null;//TODO: anpassen
				for(int i=0;i<tempRoom.getChildCount();i++){
					if(tempRoom.getChildAt(i) instanceof Room){
						childreen.add(tempRoom.getChildAt(i).toString());
					}
				}
				msgListener.sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.AVAILABLE_ROOMS,"SERVER",childreen);
				}else{
					//TODO error handling
				}
				
				break;
			case ADD_TO_WHITELIST:
				Room temp=null;
				if (message.getMessageObject() instanceof List<?>){
					List<String> dir =(List<String>)message.getMessageObject();
				
				if(serverObject.userManager.checkUserExists(message.getMessageString())){
					temp=serverObject.roomManager.getRoom(dir);
					if((temp.getOwner()!=null)&&((temp.getOwner().name==msgListener.username)||(serverObject.userManager.getUser(msgListener.username).role==ROLE.ADMIN))){
						temp.addToWhitelist(serverObject.userManager.getUser(message.getMessageString()));
						serverObject.roomManager.saveRoomMap();
					}
				}}
				break;
			case REMOVE_FROM_WHITELIST:
				Room temp2=null;
				if (message.getMessageObject() instanceof List<?>){
					List<String> dir =(List<String>)message.getMessageObject();
				
				if(serverObject.userManager.checkUserExists(message.getMessageString())){
					temp2=serverObject.roomManager.getRoom(dir);
					if((temp2.getOwner()!=null)&&((temp2.getOwner().name==msgListener.username)||(serverObject.userManager.getUser(msgListener.username).role==ROLE.ADMIN))){
						temp2.removeFromWhitelist(message.getMessageString());
						if(temp2.userExists(message.getMessageString())){
							serverObject.roomManager.moveUserTo(serverObject.userManager.getUser(message.getMessageString()), ((Room)temp2.getParent()).directory);
						}
						serverObject.roomManager.saveRoomMap();
					}
				}}
				break;
			case ADD_TO_BLACKLIST:
				Room temp3=null;
				if (message.getMessageObject() instanceof List<?>){
					List<String> dir =(List<String>)message.getMessageObject();
				
				if(serverObject.userManager.checkUserExists(message.getMessageString())){
					temp3=serverObject.roomManager.getRoom(dir);
					if((temp3.getOwner()==null)&&(serverObject.userManager.getUser(msgListener.username).role==ROLE.ADMIN)){
						temp3.addToBlacklist(serverObject.userManager.getUser(message.getMessageString()));
						serverObject.roomManager.saveRoomMap();
						if(temp3.userExists(message.getMessageString())){
							serverObject.roomManager.moveUserTo(serverObject.userManager.getUser(message.getMessageString()), ((Room)temp3.getParent()).directory);
						}
					}
				}}
				break;
			case REMOVE_FROM_BLACKLIST:
				Room temp4=null;
				if (message.getMessageObject() instanceof List<?>){
					List<String> dir =(List<String>)message.getMessageObject();
				
				if(serverObject.userManager.checkUserExists(message.getMessageString())){
					temp4=serverObject.roomManager.getRoom(dir);
					if((temp4.getOwner()==null)&&(serverObject.userManager.getUser(msgListener.username).role==ROLE.ADMIN)){
						temp4.removeFromBlacklist(message.getMessageString());
						serverObject.roomManager.saveRoomMap();
					}
				}}
				break;
			case REQUEST_WHITELIST:
				Room temp5=null;
				if (message.getMessageObject() instanceof List<?>){
					List<String> dir =(List<String>)message.getMessageObject();
					temp5=serverObject.roomManager.getRoom(dir);
				    msgListener.sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.SEND_WHITELIST,null,temp5.getWhitelist());
				}
				break;
			case REQUEST_BLACKLIST:
				Room temp6=null;
				if (message.getMessageObject() instanceof List<?>){
					List<String> dir =(List<String>)message.getMessageObject();
					temp6=serverObject.roomManager.getRoom(dir);
				    msgListener.sendSysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.SEND_BLACKLIST,null,temp6.getBlacklist());
				}
				break;
			case MAKE_PUBLIC:
				Room temp7=null;
				if (message.getMessageObject() instanceof List<?>){
					List<String> dir =(List<String>)message.getMessageObject();
				
				
					temp7=serverObject.roomManager.getRoom(dir);
					if((temp7.getOwner()!=null)&&((temp7.getOwner().name.equals(msgListener.username))||(serverObject.userManager.getUser(msgListener.username).role==ROLE.ADMIN))){
						temp7.setOwner(null);
						serverObject.roomManager.saveRoomMap();
					}
				}				
				break;
			case MAKE_PRIVATE:
				Room temp8=null;
				if (message.getMessageObject() instanceof List<?>){
					List<String> dir =(List<String>)message.getMessageObject();
					temp8=serverObject.roomManager.getRoom(dir);
				if((temp8.userExists(msgListener.username))&&(!temp8.toString().equals("Foyer"))&&(temp8.setOwner(serverObject.userManager.users.get(msgListener.username)))){					
						serverObject.roomManager.saveRoomMap();
					}else{
						msgListener.sendSysMessage(CATEGORY.ROOMMANAGEMENT,MESSAGE.COULDNT_MAKE_PRIVATE);
					}
				}
				
				break;
			case WANT_ON_WHITELIST_ACCEPTED:
				int i=serverObject.networkListener.userExists(message.getMessageString());
				if(i!=-1){
					serverObject.networkListener.messageListener.get(i).sendMessage(message);
				}
				break;
			case WANT_ON_WHITELIST_DENIED:
				int i2=serverObject.networkListener.userExists(message.getMessageString());
				if(i2!=-1){
					serverObject.networkListener.messageListener.get(i2).sendMessage(message);
				}
				break;
			case RENAME_ROOM:
				if(serverObject.userManager.getUser(msgListener.username).role==ROLE.ADMIN){
					Room temp9=serverObject.roomManager.getRoom((List<String>)message.getMessageObject());
					temp9.changeName(message.getMessageString());
				}else{
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.NEED_ADMIN_RIGHTS);
				}
				break;
			default:
				break;
			}
			break;
		case MISCELLANEOUS:
			switch(message.getMessage()){
			case WHISPER:
				int i=msgListener.serverObject.networkListener.userExists(message.getMessageString());
				if(i!=-1){
					msgListener.serverObject.networkListener.messageListener.get(i).sendMessage(message);
				}
				break;
			default:
				break;
			}
		break;
		default:
			break;
		}
		
		return false;
		
	}

	/**
	 * changes the password of an registered user
	 * 
	 * @return true if successful
	 */
	private boolean changePassword() {
		Object inputObject;
		String user = null, new_password = null, password = null;
		SysMessage sysMessage;
		
		try {
			msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.REQUEST_USERNAME);
			
			inputObject = msgListener.connector.readGeneralObject();
			
			if (inputObject instanceof SysMessage) {
				sysMessage = (SysMessage) inputObject;
				if (sysMessage.getMessage() == MESSAGE.SEND_USERNAME){
					user = sysMessage.getMessageString();
				} else {
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.MSG_NOT_EXPECTED);
					return false;
				}
			} else {
				msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.WRONG_MSG_TYPE);
				return false;
			}
			
			if (!msgListener.serverObject.userManager.checkUserExists(user)) {
				//TODO check if user is already logged in
				msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.USERNAME_UNKNOWN);
				return false;
			}
			
			if (msgListener.serverObject.userManager.users.get(user).status != User.STATUS.NORMAL) {
				msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.USERNAME_BANNED);
				return false;
			}
			
			msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.REQUEST_PASSWORD);							
			
			inputObject = msgListener.connector.readGeneralObject();
			
			if (inputObject instanceof SysMessage) {
				sysMessage = (SysMessage) inputObject;
				if (sysMessage.getMessage() == MESSAGE.SEND_PASSWORD){
					password = sysMessage.getMessageString();			
				} else {
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.MSG_NOT_EXPECTED);
					return false;
				}
			} else {
				msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.WRONG_MSG_TYPE);
				return false;
			}
			
			if (!msgListener.serverObject.userManager.checkUserPassword(user, password)) {
				msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.PASSWORD_WRONG);
				return false;
			}
			
			msgListener.sendSysMessage(CATEGORY.CHANGE_PASSWORD, MESSAGE.REQUEST_CHANGED_PASSWORD);				//now request the changed password
			
			inputObject = msgListener.connector.readGeneralObject();
			
			if (inputObject instanceof SysMessage) {
				sysMessage = (SysMessage) inputObject;
				if (sysMessage.getMessage() == MESSAGE.SEND_CHANGED_PASSWORD){
					new_password = sysMessage.getMessageString();
				} else {
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.MSG_NOT_EXPECTED);
					return false;
				}
			} else {
				msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.WRONG_MSG_TYPE);
				return false;
			}
			
			msgListener.serverObject.userManager.users.get(user).setPassword(password, new_password);
			
			msgListener.serverObject.userManager.saveUserMap();													//saves the changes
			msgListener.sendSysMessage(CATEGORY.CHANGE_PASSWORD, MESSAGE.PASSWORD_CHANGED,new_password);		//tell the client that the passwordchange was successful
			
			return true;
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * changes the username of an user
	 * @return true if successful
	 */
	private boolean changeUsername() {
		Object inputObject;
		String user = null, new_user = null, password = null;
		SysMessage sysMessage;
		
		try {
			msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.REQUEST_USERNAME);
			
			inputObject = msgListener.connector.readGeneralObject();
			
			if (inputObject instanceof SysMessage) {
				sysMessage = (SysMessage) inputObject;
				if (sysMessage.getMessage() == MESSAGE.SEND_USERNAME){
					user = sysMessage.getMessageString();
				} else {
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.MSG_NOT_EXPECTED);
					return false;
				}
			} else {
				msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.WRONG_MSG_TYPE);
				return false;
			}
			
			if (!msgListener.serverObject.userManager.checkUserExists(user)) {
				//TODO check if user is already logged in
				msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.USERNAME_UNKNOWN);
				return false;
			}
			
			if (msgListener.serverObject.userManager.users.get(user).status != User.STATUS.NORMAL) {
				msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.USERNAME_BANNED);
				return false;
			}
			
			msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.REQUEST_PASSWORD);					
			inputObject = msgListener.connector.readGeneralObject();
			
			if (inputObject instanceof SysMessage) {
				sysMessage = (SysMessage) inputObject;
				if (sysMessage.getMessage() == MESSAGE.SEND_PASSWORD){
					password = sysMessage.getMessageString();
					//System.out.println(password);
				} else {
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.MSG_NOT_EXPECTED);
					return false;
				}
			} else {
				msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.WRONG_MSG_TYPE);
				return false;
			}
			
			if (!msgListener.serverObject.userManager.checkUserPassword(user, password)) {
				msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.PASSWORD_WRONG);
				return false;
			}
			
			msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.REQUEST_CHANGED_USERNAME);
			
			inputObject = msgListener.connector.readGeneralObject();
			
			if (inputObject instanceof SysMessage) {
				sysMessage = (SysMessage) inputObject;
				if (sysMessage.getMessage() == MESSAGE.SEND_CHANGED_USERNAME){
					new_user = sysMessage.getMessageString();
				} else {
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.MSG_NOT_EXPECTED);
					return false;
				}
			} else {
				msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.WRONG_MSG_TYPE);
				return false;
			}
			
			if (msgListener.serverObject.userManager.checkUserExists(new_user)) {
				msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.USERNAME_ALREADY_EXISTS);
				return false;
			}
			
			msgListener.serverObject.userManager.users.get(user).name = new_user;
			msgListener.serverObject.userManager.users.put(new_user, msgListener.serverObject.userManager.users.get(user));
			msgListener.serverObject.userManager.users.remove(user);
			
			Room tempRoom =msgListener.serverObject.roomManager.getRoom(msgListener.serverObject.userManager.users.get(new_user).dir);
			((User)(tempRoom.users.get(user))).name=new_user;
			tempRoom.users.put(new_user, tempRoom.users.get(user));
			tempRoom.users.remove(user);
			for(int i=0;i<tempRoom.getChildCount();i++){
				if((tempRoom.getChildAt(i)instanceof User)&&(tempRoom.getChildAt(i).toString().equals(user))){
					((User)(tempRoom.getChildAt(i))).setName(new_user);
				}
					
			}
			
			msgListener.serverObject.userManager.saveUserMap();													//saves the changes
			msgListener.username=new_user;																		//changes the username of the massagelistener
			msgListener.sendSysMessage(CATEGORY.CHANGE_USERNAME, MESSAGE.USERNAME_CHANGED,new_user);			//tell the client that the namechange was successful
			SysMessage sysMsg = new SysMessage(CATEGORY.CHANGE_USERNAME,MESSAGE.USERNAME_CHANGED, new_user);	
			sysMsg.setSent(new Date());
			sysMsg.setSenderUsername(user);																		//tells which user changed his name
			msgListener.distributeMsg(sysMsg);																	//tell the other clients that a user changed his name
			SysMessage newUserMessage = new SysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.SEND_ROOM_LIST,"SERVER", msgListener.serverObject.roomManager.foyer.copyRoom());
			newUserMessage.setSent(new Date());
			newUserMessage.setSenderUsername("SERVER");
			msgListener.serverObject.networkListener.distributeMsg(newUserMessage);
//			if(msgListener.serverObject.networkListener!=null){
//				msgListener.serverObject.networkListener.distributeMsg(newUserMessage);
//			}
			
			if(msgListener.serverObject.ui instanceof GraphicalUI){
				((GraphicalUI)msgListener.serverObject.ui).updateRoomTree();
			}
			
			return true;
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * register an new user on the server
	 * @return true if successful
	 */
	private boolean register() {
		Object inputObject;
		String user = null, password = null;
		
		msgListener.sendSysMessage(CATEGORY.REGISTRATION, MESSAGE.REQUEST_NEW_USERNAME);
		
		try {
			inputObject = msgListener.connector.readGeneralObject();
		
		
			SysMessage sysMessage;
			if (inputObject instanceof SysMessage) {
				sysMessage = (SysMessage) inputObject;
				if (sysMessage.getMessage() == MESSAGE.SEND_NEW_USERNAME){
					user = sysMessage.getMessageString();
				} else {
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.MSG_NOT_EXPECTED);
					return false;
				}
			} else {
				msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.WRONG_MSG_TYPE);
				return false;
			}
			
			if (msgListener.serverObject.userManager.checkUserExists(user)) {
				msgListener.sendSysMessage(CATEGORY.REGISTRATION, MESSAGE.USERNAME_ALREADY_EXISTS);
				return false;
			}
			
			
			msgListener.sendSysMessage(CATEGORY.REGISTRATION, MESSAGE.REQUEST_NEW_PASSWORD);
			
			inputObject = msgListener.connector.readGeneralObject();
			
			if (inputObject instanceof SysMessage) {
				sysMessage = (SysMessage) inputObject;
				if (sysMessage.getMessage() == MESSAGE.SEND_NEW_PASSWORD){
					password = sysMessage.getMessageString();			
				} else {
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.MSG_NOT_EXPECTED);
					return false;
				}
			} else {
				msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.WRONG_MSG_TYPE);
				return false;
			}
			
			msgListener.serverObject.userManager.createUser(user, password);
			
			msgListener.sendSysMessage(CATEGORY.REGISTRATION,MESSAGE.REGISTRATION_SUCCESSFUL);
			
			msgListener.serverObject.ui.postInfo(String.format("%s registered at the server", user));
			return true;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return false;
	}

	/**
	 * login an user
	 * @return true if successful
	 */
	private boolean userLogin() {
		Object inputObject;
		String user = null, password = null;
		
		msgListener.sendSysMessage(CATEGORY.LOGIN, MESSAGE.REQUEST_USERNAME);
		
		try {
			inputObject = msgListener.connector.readGeneralObject();
		
		
			SysMessage sysMessage;
			if (inputObject instanceof SysMessage) {
				sysMessage = (SysMessage) inputObject;
				if (sysMessage.getMessage() == MESSAGE.SEND_USERNAME){
					user = sysMessage.getMessageString();
				} else {
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.MSG_NOT_EXPECTED);
					return false;
				}
			} else {
				msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.WRONG_MSG_TYPE);
				return false;
			}
			
			if (!msgListener.serverObject.userManager.checkUserExists(user)) {
				//TODO check if user is already logged in
				msgListener.sendSysMessage(CATEGORY.LOGIN, MESSAGE.USERNAME_UNKNOWN);
				return false;
			}
			
			if (msgListener.serverObject.userManager.users.get(user).status != User.STATUS.NORMAL) {
				msgListener.sendSysMessage(CATEGORY.LOGIN, MESSAGE.USERNAME_BANNED);
				return false;
			}
			
			if (msgListener.serverObject.networkListener.userLoggedIn(user)) {
				msgListener.sendSysMessage(CATEGORY.LOGIN, MESSAGE.ALREADY_LOGGED_IN);
				return false;
			}
						
			msgListener.sendSysMessage(CATEGORY.LOGIN, MESSAGE.REQUEST_PASSWORD);
			
			inputObject = msgListener.connector.readGeneralObject();
			
			if (inputObject instanceof SysMessage) {
				sysMessage = (SysMessage) inputObject;
				if (sysMessage.getMessage() == MESSAGE.SEND_PASSWORD){
					password = sysMessage.getMessageString();			
				} else {
					msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.MSG_NOT_EXPECTED);
					return false;
				}
			} else {
				msgListener.sendSysMessage(CATEGORY.ERROR, MESSAGE.WRONG_MSG_TYPE);
				return false;
			}
			
			if (!msgListener.serverObject.userManager.checkUserPassword(user, password)) {
				msgListener.sendSysMessage(CATEGORY.LOGIN, MESSAGE.PASSWORD_WRONG);
				return false;
			} else {
				
				msgListener.sendSysMessage(CATEGORY.LOGIN,MESSAGE.LOGGED_IN);
				
				msgListener.username = user;
				msgListener.loggedIn = true;
				SysMessage newUserMessage = new SysMessage(CATEGORY.STATUS, MESSAGE.NEW_USER_INFO, user);
				msgListener.distributeMsg(newUserMessage);
				
				msgListener.serverObject.ui.postInfo(String.format("%s connected to the server", msgListener.username));
				msgListener.serverObject.roomManager.foyer.userentry(msgListener.serverObject.userManager.getUser(user));
				List<String> tempdir=new ArrayList<String>();
				tempdir.add("Foyer");
				msgListener.serverObject.userManager.getUser(user).dir=tempdir;
				//msgListener.serverObject.roomManager.moveUserTo(msgListener.serverObject.userManager.getUser(user), tempdir);
				if(msgListener.serverObject.ui instanceof GraphicalUI){
					((GraphicalUI)msgListener.serverObject.ui).updateRoomTree();
				}
				
				SysMessage newUserMessage2 = new SysMessage(CATEGORY.ROOMMANAGEMENT, MESSAGE.SEND_ROOM_LIST,"SERVER", msgListener.serverObject.roomManager.foyer.copyRoom());
				newUserMessage2.setSent(new Date());
				newUserMessage2.setSenderUsername("SERVER");
				msgListener.distributeMsg(newUserMessage2);
				
				return true;
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}
}
